`timescale 1ns / 1ps
/*
 * Copyright (c) 2020-2021, SERI Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-10-29     Lyons        first version
 */

module pa_soc_rbm (
    m_addr_i,                   // master address
    m_data_i,                   // write data
    m_data_o,                   // read data
    m_we_i,                     // write enable

    s0_addr_o,                  // slave 0 address
    s0_data_i,                  // read data
    s0_data_o,                  // write data
    s0_we_o,                    // write enable

    s1_addr_o,                  // slave 1 address
    s1_data_i,                  // read data
    s1_data_o,                  // write data
    s1_we_o,                    // write enable

    s2_addr_o,                  // slave 2 address
    s2_data_i,                  // read data
    s2_data_o,                  // write data
    s2_we_o,                    // write enable

    s3_addr_o,                  // slave 3 address
    s3_data_i,                  // read data
    s3_data_o,                  // write data
    s3_we_o,                    // write enable

    s4_addr_o,                  // slave 4 address
    s4_data_i,                  // read data
    s4_data_o,                  // write data
    s4_we_o,                    // write enable

    s5_addr_o,                  // slave 5 address
    s5_data_i,                  // read data
    s5_data_o,                  // write data
    s5_we_o,                    // write enable

    s6_addr_o,                  // slave 6 address
    s6_data_i,                  // read data
    s6_data_o,                  // write data
    s6_we_o                     // write enable
    );

`include "../pa_chip_param.v"

localparam SLAVE_0_ADDR         = 4'b0000; //rom    0x0000_0000 ~ 0x0fff_ffff
localparam SLAVE_1_ADDR         = 4'b0001; //ram    0x1000_0000 ~ 0x1fff_ffff
localparam SLAVE_2_ADDR         = 4'b0010; //timer  0x2000_0000 ~ 0x2fff_ffff
localparam SLAVE_3_ADDR         = 4'b0011; //uart   0x3000_0000 ~ 0x3fff_ffff
localparam SLAVE_4_ADDR         = 4'b0100; //i2c    0x4000_0000 ~ 0x4fff_ffff
localparam SLAVE_5_ADDR         = 4'b0101; //spi    0x5000_0000 ~ 0x5fff_ffff
localparam SLAVE_6_ADDR         = 4'b0110; //lcd    0x6000_0000 ~ 0x6fff_ffff

input  [`ADDR_BUS_WIDTH-1:0]    m_addr_i;
input  [`DATA_BUS_WIDTH-1:0]    m_data_i;
output [`DATA_BUS_WIDTH-1:0]    m_data_o;
input                           m_we_i;

output [`ADDR_BUS_WIDTH-1:0]    s0_addr_o;
input  [`DATA_BUS_WIDTH-1:0]    s0_data_i;
output [`DATA_BUS_WIDTH-1:0]    s0_data_o;
output                          s0_we_o;

output [`ADDR_BUS_WIDTH-1:0]    s1_addr_o;
input  [`DATA_BUS_WIDTH-1:0]    s1_data_i;
output [`DATA_BUS_WIDTH-1:0]    s1_data_o;
output                          s1_we_o;

output [`ADDR_BUS_WIDTH-1:0]    s2_addr_o;
input  [`DATA_BUS_WIDTH-1:0]    s2_data_i;
output [`DATA_BUS_WIDTH-1:0]    s2_data_o;
output                          s2_we_o;

output [`ADDR_BUS_WIDTH-1:0]    s3_addr_o;
input  [`DATA_BUS_WIDTH-1:0]    s3_data_i;
output [`DATA_BUS_WIDTH-1:0]    s3_data_o;
output                          s3_we_o;

output [`ADDR_BUS_WIDTH-1:0]    s4_addr_o;
input  [`DATA_BUS_WIDTH-1:0]    s4_data_i;
output [`DATA_BUS_WIDTH-1:0]    s4_data_o;
output                          s4_we_o;

output [`ADDR_BUS_WIDTH-1:0]    s5_addr_o;
input  [`DATA_BUS_WIDTH-1:0]    s5_data_i;
output [`DATA_BUS_WIDTH-1:0]    s5_data_o;
output                          s5_we_o;

output [`ADDR_BUS_WIDTH-1:0]    s6_addr_o;
input  [`DATA_BUS_WIDTH-1:0]    s6_data_i;
output [`DATA_BUS_WIDTH-1:0]    s6_data_o;
output                          s6_we_o;

wire [`ADDR_BUS_WIDTH-1:0]      m_addr_i;
wire [`DATA_BUS_WIDTH-1:0]      m_data_i;
reg  [`DATA_BUS_WIDTH-1:0]      m_data_o;
wire                            m_we_i;

reg  [`ADDR_BUS_WIDTH-1:0]      s0_addr_o;
wire [`DATA_BUS_WIDTH-1:0]      s0_data_i;
reg  [`DATA_BUS_WIDTH-1:0]      s0_data_o;
reg                             s0_we_o;

reg  [`ADDR_BUS_WIDTH-1:0]      s1_addr_o;
wire [`DATA_BUS_WIDTH-1:0]      s1_data_i;
reg  [`DATA_BUS_WIDTH-1:0]      s1_data_o;
reg                             s1_we_o;

reg  [`ADDR_BUS_WIDTH-1:0]      s2_addr_o;
wire [`DATA_BUS_WIDTH-1:0]      s2_data_i;
reg  [`DATA_BUS_WIDTH-1:0]      s2_data_o;
reg                             s2_we_o;

reg  [`ADDR_BUS_WIDTH-1:0]      s3_addr_o;
wire [`DATA_BUS_WIDTH-1:0]      s3_data_i;
reg  [`DATA_BUS_WIDTH-1:0]      s3_data_o;
reg                             s3_we_o;

reg  [`ADDR_BUS_WIDTH-1:0]      s4_addr_o;
wire [`DATA_BUS_WIDTH-1:0]      s4_data_i;
reg  [`DATA_BUS_WIDTH-1:0]      s4_data_o;
reg                             s4_we_o;

reg  [`ADDR_BUS_WIDTH-1:0]      s5_addr_o;
wire [`DATA_BUS_WIDTH-1:0]      s5_data_i;
reg  [`DATA_BUS_WIDTH-1:0]      s5_data_o;
reg                             s5_we_o;

reg  [`ADDR_BUS_WIDTH-1:0]      s6_addr_o;
wire [`DATA_BUS_WIDTH-1:0]      s6_data_i;
reg  [`DATA_BUS_WIDTH-1:0]      s6_data_o;
reg                             s6_we_o;


always @ (*) begin
    case (m_addr_i[31:28])
        SLAVE_0_ADDR : m_data_o[`DATA_BUS_WIDTH-1:0] = s0_data_i[`DATA_BUS_WIDTH-1:0];
        SLAVE_1_ADDR : m_data_o[`DATA_BUS_WIDTH-1:0] = s1_data_i[`DATA_BUS_WIDTH-1:0];
        SLAVE_2_ADDR : m_data_o[`DATA_BUS_WIDTH-1:0] = s2_data_i[`DATA_BUS_WIDTH-1:0];
        SLAVE_3_ADDR : m_data_o[`DATA_BUS_WIDTH-1:0] = s3_data_i[`DATA_BUS_WIDTH-1:0];
        SLAVE_4_ADDR : m_data_o[`DATA_BUS_WIDTH-1:0] = s4_data_i[`DATA_BUS_WIDTH-1:0];
        SLAVE_5_ADDR : m_data_o[`DATA_BUS_WIDTH-1:0] = s5_data_i[`DATA_BUS_WIDTH-1:0];
        SLAVE_6_ADDR : m_data_o[`DATA_BUS_WIDTH-1:0] = s6_data_i[`DATA_BUS_WIDTH-1:0];
        default      : m_data_o[`DATA_BUS_WIDTH-1:0] = `ZERO_WORD;
    endcase
end

always @ (*) begin
    s0_addr_o[`ADDR_BUS_WIDTH-1:0] = `ZERO_WORD;
    s0_data_o[`DATA_BUS_WIDTH-1:0] = `ZERO_WORD;
    s0_we_o                        = `INVALID;

    s1_addr_o[`ADDR_BUS_WIDTH-1:0] = `ZERO_WORD;
    s1_data_o[`DATA_BUS_WIDTH-1:0] = `ZERO_WORD;
    s1_we_o                        = `INVALID;

    s2_addr_o[`ADDR_BUS_WIDTH-1:0] = `ZERO_WORD;
    s2_data_o[`DATA_BUS_WIDTH-1:0] = `ZERO_WORD;
    s2_we_o                        = `INVALID;

    s3_addr_o[`ADDR_BUS_WIDTH-1:0] = `ZERO_WORD;
    s3_data_o[`DATA_BUS_WIDTH-1:0] = `ZERO_WORD;
    s3_we_o                        = `INVALID;

    s4_addr_o[`ADDR_BUS_WIDTH-1:0] = `ZERO_WORD;
    s4_data_o[`DATA_BUS_WIDTH-1:0] = `ZERO_WORD;
    s4_we_o                        = `INVALID;

    s5_addr_o[`ADDR_BUS_WIDTH-1:0] = `ZERO_WORD;
    s5_data_o[`DATA_BUS_WIDTH-1:0] = `ZERO_WORD;
    s5_we_o                        = `INVALID;

    s6_addr_o[`ADDR_BUS_WIDTH-1:0] = `ZERO_WORD;
    s6_data_o[`DATA_BUS_WIDTH-1:0] = `ZERO_WORD;
    s6_we_o                        = `INVALID;

    case (m_addr_i[31:28])
        SLAVE_0_ADDR : begin
            s0_addr_o[`ADDR_BUS_WIDTH-1:0] = {4'b0, m_addr_i[27:0]};
            s0_data_o[`DATA_BUS_WIDTH-1:0] = m_data_i[`DATA_BUS_WIDTH-1:0];
            s0_we_o                        = m_we_i;
        end
        SLAVE_1_ADDR : begin
            s1_addr_o[`ADDR_BUS_WIDTH-1:0] = {4'b0, m_addr_i[27:0]};
            s1_data_o[`DATA_BUS_WIDTH-1:0] = m_data_i[`DATA_BUS_WIDTH-1:0];
            s1_we_o                        = m_we_i;
        end
        SLAVE_2_ADDR : begin
            s2_addr_o[`ADDR_BUS_WIDTH-1:0] = {4'b0, m_addr_i[27:0]};
            s2_data_o[`DATA_BUS_WIDTH-1:0] = m_data_i[`DATA_BUS_WIDTH-1:0];
            s2_we_o                        = m_we_i;
        end
        SLAVE_3_ADDR : begin
            s3_addr_o[`ADDR_BUS_WIDTH-1:0] = {4'b0, m_addr_i[27:0]};
            s3_data_o[`DATA_BUS_WIDTH-1:0] = m_data_i[`DATA_BUS_WIDTH-1:0];
            s3_we_o                        = m_we_i;
        end
        SLAVE_4_ADDR : begin
            s4_addr_o[`ADDR_BUS_WIDTH-1:0] = {4'b0, m_addr_i[27:0]};
            s4_data_o[`DATA_BUS_WIDTH-1:0] = m_data_i[`DATA_BUS_WIDTH-1:0];
            s4_we_o                        = m_we_i;
        end
        SLAVE_5_ADDR : begin
            s5_addr_o[`ADDR_BUS_WIDTH-1:0] = {4'b0, m_addr_i[27:0]};
            s5_data_o[`DATA_BUS_WIDTH-1:0] = m_data_i[`DATA_BUS_WIDTH-1:0];
            s5_we_o                        = m_we_i;
        end
        SLAVE_6_ADDR : begin
            s6_addr_o[`ADDR_BUS_WIDTH-1:0] = {4'b0, m_addr_i[27:0]};
            s6_data_o[`DATA_BUS_WIDTH-1:0] = m_data_i[`DATA_BUS_WIDTH-1:0];
            s6_we_o                        = m_we_i;
        end
        default : begin
        end
    endcase
end

endmodule